package com.ruoyi.business.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import com.ruoyi.business.domain.*;
import com.ruoyi.business.mapper.TDeviceMapper;
import com.ruoyi.business.mapper.TIncomeLogMapper;
import com.ruoyi.business.service.ITAddressService;
import com.ruoyi.business.service.ITOrderItemService;
import com.ruoyi.business.service.ITProductService;
import com.ruoyi.common.annotation.DataScope;
import com.ruoyi.common.constant.Constants;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.ruoyi.business.mapper.TOrderMapper;
import com.ruoyi.business.service.ITOrderService;
import com.ruoyi.business.mapper.TOrderItemMapper;
import org.springframework.transaction.annotation.Transactional;
import com.ruoyi.common.utils.uuid.IdUtils;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * 订单管理Service业务层处理
 * 
 * @author laoguo
 * @date 2025-08-12
 */
@Service
public class TOrderServiceImpl implements ITOrderService 
{
    @Autowired
    private TOrderMapper tOrderMapper;

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ITProductService productService;

    @Autowired
    private ITAddressService addressService;

    @Autowired
    private TOrderItemMapper tOrderItemMapper;

    @Autowired
    private TIncomeLogMapper incomeLogMapper;

    @Autowired
    private ITOrderItemService itOrderItemService;

    @Autowired
    private TDeviceMapper deviceMapper;

    /**
     * 查询订单管理
     * 
     * @param orderId 订单管理主键
     * @return 订单管理
     */
    @Override
    public TOrder selectTOrderByOrderId(Long orderId)
    {
        return tOrderMapper.selectTOrderByOrderId(orderId);
    }

    /**
     * 查询订单管理列表
     * 
     * @param tOrder 订单管理
     * @return 订单管理
     */
    @Override
    public List<TOrder> selectTOrderList(TOrder tOrder)
    {
        return tOrderMapper.selectTOrderList(tOrder);
    }

    /**
     * 新增订单管理
     * 
     * @param tOrder 订单管理
     * @return 结果
     */
    @Override
    public int insertTOrder(TOrder tOrder)
    {
        tOrder.setCreateTime(DateUtils.getNowDate());
        return tOrderMapper.insertTOrder(tOrder);
    }

    /**
     * 修改订单管理
     * 
     * @param tOrder 订单管理
     * @return 结果
     */
    @Override
    public int updateTOrder(TOrder tOrder)
    {
        tOrder.setUpdateTime(DateUtils.getNowDate());
        return tOrderMapper.updateTOrder(tOrder);
    }

    /**
     * 批量删除订单管理
     * 
     * @param orderIds 需要删除的订单管理主键
     * @return 结果
     */
    @Override
    public int deleteTOrderByOrderIds(Long[] orderIds)
    {
        return tOrderMapper.deleteTOrderByOrderIds(orderIds);
    }

    /**
     * 删除订单管理信息
     * 
     * @param orderId 订单管理主键
     * @return 结果
     */
    @Override
    public int deleteTOrderByOrderId(Long orderId)
    {
        return tOrderMapper.deleteTOrderByOrderId(orderId);
    }

    /**
     * 生成订单号
     * @return 订单号字符串
     */
    private String generateOrderSn() {
        // 格式化当前时间，例如 "202508121630"
        String dateTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));

        // 从Redis获取一个当日自增的序列号
        String date = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String redisKey = "order_sn_incr:" + date;
        Long increment = redisCache.increment(redisKey);

        // 如果是当天的第一个订单，设置key的过期时间为24小时
        if (increment == 1) {
            redisCache.expire(redisKey, 24, TimeUnit.HOURS);
        }

        // 拼接订单号：日期时间 + 6位自增序列（不足6位前面补0）
        return dateTime + String.format("%06d", increment);
    }

    @Override
    public Map<String, Object> previewOrder(Map<String, Object> params) {
        String from = params.get("from").toString();
        Long userId = SecurityUtils.getUserId();

        // 步骤1：解析前端参数，获取要结算的商品ID和数量
        Map<Long, Integer> productQuantityMap = new HashMap<>();
        if ("cart".equals(from)) {
            // 注意：JSON传过来的数字列表可能被解析为Integer，需要转换
            List<Integer> productIdsInt = (List<Integer>) params.get("productIds");
            List<Long> productIds = productIdsInt.stream().map(Long::valueOf).collect(Collectors.toList());

            String cartKey = Constants.CART_KEY + userId;
            for (Long productId : productIds) {
                Integer quantity = redisCache.getCacheMapValue(cartKey, productId.toString());
                if (quantity != null && quantity > 0) {
                    productQuantityMap.put(productId, quantity);
                }
            }
        } else if ("product".equals(from)) {
            Long productId = Long.valueOf(params.get("productId").toString());
            Integer quantity = Integer.valueOf(params.get("quantity").toString());
            productQuantityMap.put(productId, quantity);
        }

        if (productQuantityMap.isEmpty()) {
            throw new ServiceException("没有需要结算的商品");
        }

        // 步骤2：批量从数据库查询商品最新信息（价格、库存、状态等）
        List<Long> allProductIds = new ArrayList<>(productQuantityMap.keySet());
        List<TProduct> products = productService.selectTProductByProductIds(allProductIds);

        // 校验商品是否都有效
        if (products.size() != allProductIds.size()) {
            throw new ServiceException("包含已下架或不存在的商品");
        }
        for(TProduct p : products){
            if(!"0".equals(p.getStatus())){
                throw new ServiceException("商品[" + p.getProductName() + "]已下架");
            }
        }

        // 步骤3：组装订单项，并计算商品总金额
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<Map<String, Object>> orderItems = new ArrayList<>();
        for (TProduct product : products) {
            Map<String, Object> item = new HashMap<>();
            Integer quantity = productQuantityMap.get(product.getProductId());
            item.put("productId", product.getProductId());
            item.put("productName", product.getProductName());
            item.put("coverImage", product.getCoverImage());
            item.put("price", product.getPrice());
            item.put("quantity", quantity);
            orderItems.add(item);

            // 累加总金额
            totalAmount = totalAmount.add(product.getPrice().multiply(new BigDecimal(quantity)));
        }

        // 步骤4：查询用户的默认收货地址
        TAddress defaultAddress = addressService.selectDefaultAddressByUserId(userId);

        // 步骤5：计算运费和最终应付金额 (运费暂时固定为5元)
        BigDecimal shippingFee = new BigDecimal("5.00");
        BigDecimal payAmount = totalAmount.add(shippingFee);

        // 步骤6：组装所有信息并返回
        Map<String, Object> result = new HashMap<>();
        result.put("defaultAddress", defaultAddress);
        result.put("orderItems", orderItems);
        result.put("totalAmount", totalAmount.toString());
        result.put("shippingFee", shippingFee.toString());
        result.put("payAmount", payAmount.toString());

        return result;
    }

    public TOrder createOrder(Map<String, Object> params) {
        Long userId = SecurityUtils.getUserId();
        Long addressId = Long.valueOf(params.get("addressId").toString());
        List<Map<String, Object>> itemsParam = (List<Map<String, Object>>) params.get("items");
        String remark = params.get("remark") != null ? params.get("remark").toString() : "";

        if (itemsParam == null || itemsParam.isEmpty()) {
            throw new ServiceException("订单商品不能为空");
        }

        // 步骤1: 重新校验价格和库存，并扣减库存
        BigDecimal totalAmount = BigDecimal.ZERO;
        List<TProduct> products = new ArrayList<>();
        for (Map<String, Object> item : itemsParam) {
            Long productId = Long.valueOf(item.get("productId").toString());
            Integer quantity = Integer.valueOf(item.get("quantity").toString());

            TProduct product = productService.selectTProductByProductId(productId);
            if(product == null || !"0".equals(product.getStatus())) {
                throw new ServiceException("商品不存在或已下架");
            }

            // 安全扣减库存
            int rows = productService.decreaseStock(productId, quantity);
            if (rows == 0) {
                throw new ServiceException("商品[" + product.getProductName() + "]库存不足");
            }

            // 累加总金额（使用数据库中的单价，防止前端篡改）
            totalAmount = totalAmount.add(product.getPrice().multiply(new BigDecimal(quantity)));
            products.add(product);
        }

        // 步骤2: 创建订单主表 (t_order)
        TAddress address = addressService.selectTAddressByAddressId(addressId);
        if (address == null) {
            throw new ServiceException("收货地址不存在");
        }

        TOrder order = new TOrder();
        order.setOrderSn(generateOrderSn());
        order.setUserId(userId);
        order.setOrderType("0"); // 0=商品订单
        order.setOrderStatus("0"); // 0=待付款
        order.setTotalAmount(totalAmount);
        order.setPayAmount(totalAmount.add(new BigDecimal("5.00"))); // 加上5元运费
        order.setAddressId(addressId);
        order.setConsigneeName(address.getConsigneeName());
        order.setPhoneNumber(address.getPhoneNumber());
        order.setFullAddress(address.getProvince() + address.getCity() + address.getDistrict() + address.getDetailAddress());
        order.setRemark(remark);
        order.setCreateBy(SecurityUtils.getUsername());

        tOrderMapper.insertTOrder(order); // 插入后，MyBatis会自动回填orderId

        // 步骤3: 创建订单详情表记录 (t_order_item)
        for (Map<String, Object> item : itemsParam) {
            Long productId = Long.valueOf(item.get("productId").toString());
            Integer quantity = Integer.valueOf(item.get("quantity").toString());

            // 从已查询的商品列表中找到对应商品
            TProduct currentProduct = products.stream().filter(p -> p.getProductId().equals(productId)).findFirst().get();

            TOrderItem orderItem = new TOrderItem();
            orderItem.setOrderId(order.getOrderId());
            orderItem.setProductId(productId);
            orderItem.setProductName(currentProduct.getProductName());
            orderItem.setProductImage(currentProduct.getCoverImage());
            orderItem.setProductPrice(currentProduct.getPrice());
            orderItem.setQuantity(Long.valueOf(quantity)); // 假设你的OrderItem中quantity是Long类型

            tOrderItemMapper.insertTOrderItem(orderItem);
        }

        // 步骤4: 清空购物车中已下单的商品
        String cartKey = Constants.CART_KEY + userId;
        // **【核心修正】**
        for (Map<String, Object> item : itemsParam) {
            String productIdStr = item.get("productId").toString();
            redisCache.deleteCacheMapValue(cartKey, productIdStr);
        }

        return order;
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 开启事务
    public boolean processPaySuccess(Long orderId) {
        // 步骤1: 查询并锁定订单，防止并发问题
        // 使用 select ... for update 进行悲观锁定
        TOrder order = tOrderMapper.selectTOrderByIdForUpdate(orderId);

        // 步骤2: 校验订单状态
        if (order == null) {
            throw new ServiceException("订单不存在");
        }
        if (!"0".equals(order.getOrderStatus())) {
            // 如果订单不是“待付款”状态，说明可能已经支付或关闭，无需重复处理
            System.out.println("订单" + order.getOrderSn() + "状态不是待付款，无需处理支付结果");
            return true; // 直接返回成功，避免微信重复通知等问题
        }

        // 步骤3: 更新订单状态
        order.setOrderStatus("1"); // 变为“待发货” (如果是商品订单) 或 "3" (已完成，如果是碾米订单)
        order.setPayType("3"); // 假设 '3' 代表模拟支付
        order.setPayTime(new Date());
        order.setUpdateBy(SecurityUtils.getUsername()); // 记录操作人

        int updateRows = tOrderMapper.updateTOrder(order);
        if (updateRows == 0) {
            throw new ServiceException("更新订单状态失败");
        }

        // 步骤4: 记录收益流水 (核心扩展业务)
        // 这里只是一个示例，实际的分成逻辑可能更复杂
        if (order.getPayAmount().compareTo(BigDecimal.ZERO) > 0) {
            TIncomeLog incomeLog = new TIncomeLog();

            // 假设暂时将收益全部记给平台关联的某个用户(例如 user_id=1, admin)
            // 实际项目中需要根据订单关联的设备，找到合作商和经销商，按比例计算分成
            incomeLog.setUserId(1L); // 示例：收益归属admin
            incomeLog.setUserType("0"); // 示例：角色类型
            incomeLog.setIncomeType("0".equals(order.getOrderType()) ? "1" : "0"); // 根据订单类型判断
            incomeLog.setIncomeAmount(order.getPayAmount()); // 示例：全额收益
            incomeLog.setSourceId(order.getOrderId());
            incomeLog.setSourceSn(order.getOrderSn());
            incomeLog.setDeviceId(order.getDeviceId());
            incomeLog.setRemark("订单支付成功，产生收益");

            incomeLogMapper.insertTIncomeLog(incomeLog);
        }

        // 步骤5: (可选) 发送通知
        // 比如，通过WebSocket或消息队列通知前端支付成功

        return true;
    }

    @Override
    @DataScope(deptAlias = "d", userAlias = "u")
    public List<TOrder> selectOrderListWithItems(TOrder order) {
        return tOrderMapper.selectOrderListWithItems(order);
    }

    @Override
    public TOrder selectOrderDetailById(Long orderId) {
        return tOrderMapper.selectOrderDetailById(orderId);
    }

    @Override
    public boolean checkPartnerOrderPermission(Long partnerId, Long orderId) {
        TOrder order = tOrderMapper.selectTOrderByOrderId(orderId);
        if (order == null || order.getDeviceId() == null) return false;
        TDevice device = deviceMapper.selectTDeviceByDeviceId(order.getDeviceId());
        return device != null && partnerId.equals(device.getPartnerId());
    }

    @Override
    public boolean checkDistributorOrderPermission(Long distributorId, Long orderId) {
        TOrder order = tOrderMapper.selectTOrderByOrderId(orderId);
        if (order == null || order.getDeviceId() == null) return false;
        TDevice device = deviceMapper.selectTDeviceByDeviceId(order.getDeviceId());
        return device != null && distributorId.equals(device.getDistributorId());
    }
}
